package cn.wolfcode.interceptor;

import cn.wolfcode.annotation.RequireLogin;
import cn.wolfcode.domain.UserInfo;
import cn.wolfcode.redis.IUserInfoRedisService;
import cn.wolfcode.redis.util.RedisKeysUtil;
import cn.wolfcode.util.JsonResult;
import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description: 配置拦截器
 * @Author: 伍家钰
 * @Date: 2020/8/9 22:29
 * @Version: 1.0
 */
public class CheckLoginInterceptor implements HandlerInterceptor {
    @Resource
    private IUserInfoRedisService userInfoRedisService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        /*
         * 2.解决拦截器的跨域访问问题:只有动态请求(请求的后缀是.jsp等,.html的是静态请求)handler才是HandlerMethod的实例
         *  为什么在项目启动类中做了跨域访问的配置在拦截器中还是要做跨域访问的配置?
         *  因为跨域访问时handler不是HandlerMethod的实例,如果不写这可判,则跨域访问最终会因为没有token而被拦截
         */
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // 判断方法是否有贴注解,贴了则要登入才能访问
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        // 获取请求头,放在这表示方法无论有没有贴注解都可以延长token的存活时间
        String key = request.getHeader("token");
        // 3.获取登入对象
        UserInfo userInfo = userInfoRedisService.getByToken(key);
        // 如果没有贴注解则直接放行
        if (handlerMethod.hasMethodAnnotation(RequireLogin.class)) {

            if (userInfo == null) {
                //没登入,设置响应头
                response.setContentType("application/json;charset:utf-8");
                // 输出提示信息
                response.getWriter().write(JSON.toJSONString(JsonResult.noLogin()));
                // 不放行
                return false;
            }
        }
        return true;
    }
}
